#ifndef _SOCKET_SOCKET_H_
#define _SOCKET_SOCKET_H_

#include <string>
using std::string;

#include "byte.h"
#include "queue.h"
#include "sysdef.h"
#include "singleton.h"

#ifdef WIN32

#define SOCKET_ERRNO    WSAGetLastError()
#define SOCKET_CLOSE    closesocket
#define socklen_t       int

#else

#define SOCKET_ERRNO    errno
#define SOCKET_CLOSE    close

#endif

void set_linger(int fd);

void set_buf_size(int fd);

void set_reuse_addr(int fd);

void set_keep_alive(int fd);

void set_time_out(int fd, int timeout = 30);

void set_blocking(int fd, bool isblock = false);

class CStartSocket
{
    friend class CSingleton<CStartSocket>;

    CStartSocket();

public:

    ~CStartSocket();
};

#define sStartSocket CSingleton<CStartSocket>::Instance()

struct SocketInfo
{
public:

   SocketInfo();

    ~SocketInfo();

    string _recvbuf;
    
    char _addrinfo[64];

    int _fd; char _ip[16]; ushort _port;
};

string en_addr_info(int fd, const char* ip, ushort port);

bool de_addr_info(const char* addrinfo, int& fd, char* ip, ushort& port);

typedef CByteBlock RecvBlock;

typedef CQueue<RecvBlock*> RecvBlockQueue;

typedef CByteBuffer SendBuffer;

typedef CQueue<CByteBuffer*> SendBufferQueue;

typedef void (*socket_callback_func)(string addrinfo);

class CLog;

class CSocket
{
public:

    virtual ~CSocket();
    
    bool ConnectToServer();

    void SetBlock(bool isblock);
    
    void SetTimeOut(int timeout);

    void SetCallbackFunc(socket_callback_func func);

protected:

    CSocket();

    virtual int Recv(const char* addrinfo, int fd, char* outbuf, int outlen);
    
    virtual int Send(const char* addrinfo, int fd, const char* inbuf, int inlen);

protected:

    int  m_timeout;

    bool m_isblock;

    CLog*   m_log;

    SocketInfo  m_socketinfo;

    socket_callback_func m_callbackfunc;
};

#endif //_SOCKET_SOCKET_H_
